package soar.template.springboot.service.hello.configuration;

import java.time.Duration;

import javax.annotation.Resource;

import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;

import soar.template.springboot2.share.Const;
import soar.template.springboot2.websocket.server.service.Receiver;


@Configuration
public class RedisConfiguration
{
    @Value("${redis.main.host}")
    private String main_host;

    @Value("${redis.main.port}")
    private int main_port;

    @Bean
    public RedisMessageListenerContainer container()
    {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(mainRedisConnectionFactory());
        container.addMessageListener(listenAdapter(),
                new PatternTopic(Const.RedisKey.MESSAGE));
        return container;
    }

    @Bean
    public MessageListenerAdapter listenAdapter()
    {
        return new MessageListenerAdapter(receiver, "receiveMessage");
    }

    @Resource
    private Receiver receiver;

    @Bean(name = "mainRedisTemplate")
    public StringRedisTemplate mainRedisTemplate()
    {
        StringRedisTemplate template = new StringRedisTemplate(
                mainRedisConnectionFactory());
        return template;
    }

    @Bean(name = "mainRedisConnectionFactory")
    public RedisConnectionFactory mainRedisConnectionFactory()
    {
        return create_factory(main_host, main_port);
    }

    private RedisConnectionFactory create_factory(String host, int port)
    {
        RedisStandaloneConfiguration standalone_config = new RedisStandaloneConfiguration();
        standalone_config.setHostName(host);
        standalone_config.setPort(port);

        GenericObjectPoolConfig<?> pool_config = new GenericObjectPoolConfig<>();
        pool_config.setMaxTotal(100);
        pool_config.setBlockWhenExhausted(true);
        pool_config.setMaxWaitMillis(1000);
        pool_config.setTestOnBorrow(true);
        pool_config.setTimeBetweenEvictionRunsMillis(10 * 1000);
        pool_config.setMinEvictableIdleTimeMillis(30 * 1000);
        LettucePoolingClientConfiguration lettuce_config = LettucePoolingClientConfiguration
                .builder().commandTimeout(Duration.ofMillis(1000))
                .poolConfig(pool_config).build();

        return new LettuceConnectionFactory(standalone_config, lettuce_config);
    }

}
